package com.github.livebase.log;

import android.content.res.XmlResourceParser;
import android.text.TextUtils;
import android.util.Log;

import com.github.livebase.util.base.ObjectsUtil;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName LoggerConfig
 * @description:
 * @author: biao532
 * @create: 2024-02-02 21:14
 * @Version 1.0
 **/
public class LoggerDefinitionUtil {
    public static List<LoggerDefinition> readFromXml(File file) {
        if (!file.exists()) {
            return ObjectsUtil.Empty.LIST;
        }
        List<LoggerDefinition> list = new ArrayList<>(0);
        try(FileInputStream inputStream = new FileInputStream(file)) {
            list = readFromXml(inputStream);
        } catch (IOException e) {
            LoggerFactory.getLogger(LoggerDefinitionUtil.class)
                    .warn("LoggerDefinitionUtil", "please resource " + file.getAbsolutePath(), e);
        }
        return list;
    }
    public static List<LoggerDefinition> readFromXml(InputStream inputStream) {

        List<LoggerDefinition> definitions = new ArrayList<>();
        int type = XmlPullParser.END_DOCUMENT;
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new InputStreamReader(inputStream));

            while ((type = parser.getEventType()) != XmlPullParser.END_DOCUMENT) {
                if (type == XmlResourceParser.START_TAG) {
                    String name = parser.getName();
                    if (!"logger".equals(name)) {
                        parser.next();
                        continue;
                    }
                    String pkgName = parser.getAttributeValue("", "package");
                    String className = parser.getAttributeValue("", "class");
                    if (TextUtils.isEmpty(pkgName) || TextUtils.isEmpty(className)) {
                        parser.next();
                        continue;
                    }
                    LoggerDefinition definition = new LoggerDefinition(className, pkgName);
                    parser.next();
                    parameter(parser, definition);
                    definitions.add(definition);
                }
                parser.next();
            }
        } catch (XmlPullParserException | IOException | LoggerException e) {
            LoggerFactory.getLogger(LoggerDefinitionUtil.class)
                    .warn("LoggerDefinitionUtil", "parse xml to LoggerDefinition error", e);
        }
        return definitions;
    }
    private static void parameter(XmlPullParser parser, LoggerDefinition config) throws XmlPullParserException, IOException, LoggerException {
        int type = XmlPullParser.END_TAG;
        while ((type = parser.getEventType()) != XmlPullParser.END_TAG) {
            if (type == XmlResourceParser.START_TAG) {
                String name = parser.getName();
                String clazz = parser.getAttributeValue("", "class");
                String value = parser.nextText();
                if (!TextUtils.isEmpty(value)) {
                    config.addParameter(name, varVal(clazz, value), varClass(clazz));
                }
            }
            parser.next();
        }
    }

    private static Class varClass(String clazz) throws LoggerException {
        Class c = null;
        switch (clazz) {
            case "Boolean": c = Boolean.class;break;
            case "boolean": c = boolean.class;break;
            case "Byte": c = Byte.class;break;
            case "byte": c = byte.class;break;
            case "Integer": c = Integer.class;break;
            case "int": c = int.class;break;
            case "Float": c = Float.class;break;
            case "float": c = float.class;break;
            case "Long": c = Long.class;break;
            case "long": c = long.class;break;
            case "Double":  c = Double.class;break;
            case "double": c = double.class;break;
            case "String": c = String.class;break;
            case "File": c = File.class;break;
            default: {}
        }
        if (c != null) {
            return c;
        }
        throw new LoggerException(String.format("unsupported class for %s, val=%s", clazz));
    }
    private static Object varVal(String clazz, String val) throws LoggerException {
        Object c = null;
        switch (clazz) {
            case "Boolean":
            case "boolean": c = Boolean.valueOf(val).booleanValue();break;
            case "Byte":
            case "byte": c = Byte.valueOf(val).byteValue();break;
            case "Integer":
            case "int": c = Integer.valueOf(val).intValue();break;
            case "Float":
            case "float": c = Float.valueOf(val).floatValue();break;
            case "Long":
            case "long": c = Long.valueOf(val).longValue();break;
            case "Double":
            case "double": c = Double.valueOf(val).doubleValue();break;
            case "String": c = val;break;
            case "File": c = new File(val);break;
            default: {}
        }
        if (c != null) {
            return c;
        }
        throw new LoggerException(String.format("unsupported class for %s, val=%s", clazz, val));
    }
}
